package com.health.userbackstage.config;

import com.alibaba.fastjson.JSON;
import com.health.userbackstage.filters.LoginFilter;
import com.health.userbackstage.filters.VerifyTokenFilter;
import com.health.userbackstage.mapper.PermissionMapper;
import com.health.userbackstage.pojo.Permission;
import com.health.userbackstage.pojo.result.Result;
import com.health.userbackstage.pojo.result.ResultEnum;
import com.health.userbackstage.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter implements InitializingBean {

    @Autowired
    private PermissionMapper permissionMapper;
    private List<Permission> permissionList;

    @Override
    public void afterPropertiesSet() throws Exception {
        permissionList = permissionMapper.findAll();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //security中默认的页面访问是有特殊标记的，如果页面发送的请求到security中没有这个特殊标记，不允许访问
        //开发中会关闭跨站伪造验证Cross-site request forgery(可以让所有页面正常访问后台资源)
        http.csrf().disable();
        //设置跨域，基于同源策略的Cross Origin Resource Sharin跨域资源共享
        http.cors().configurationSource(ccs());

        for (Permission permission : permissionList) {
            //查询资源所需要的角色（权限）
            //需要在xml中配置rname
            List<String> roles = permission.getRoles();
            //antMatchers用于匹配url，这段代码用于授权请求，判断url是否撇皮，如果匹配则需要具备指定的角色才能访问
            http.authorizeRequests().antMatchers(permission.getKeyword())
                    .hasAnyAuthority(roles.toArray(new String[0]));
        }

            //配置哪些资源的访问需要登录 （***注意：在指定路径需要认证或者放行时，一定要将大的路径范围放最后）
        http.authorizeRequests()
                //表示所有资源的访问必须登录，没有登录就报403
                .antMatchers("/**").authenticated();
//                        .antMatchers("/**").permitAll();


        http.exceptionHandling()
                //未登录时的响应数据
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                        Result result = Result.fail(ResultEnum.NO_LOGIN.getCode(), ResultEnum.NO_LOGIN.getMessage());
                        response.setContentType("application/json;charset=utf-8");
                        response.getWriter().write(JSON.toJSONString(result));
                    }
                })
                //登陆成功但是没有访问权限
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {

                        Result result = Result.fail(ResultEnum.NO_ROLE);
                        response.getWriter().write(JSON.toJSONString(result));
                    }
                });
//        http.formLogin();
        http.addFilter(new LoginFilter(authenticationManager()))
                .addFilter(new VerifyTokenFilter(authenticationManager()));
        //将登录过滤器添加到security过滤器链中
    }

    private CorsConfigurationSource ccs() {
        //基于url判断的依据
        UrlBasedCorsConfigurationSource ubccs = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfig = new CorsConfiguration();
        //允许哪些域的访问, * 表示任何域都可以访问
        //这个开启了就会在header加上Access-Control-Allow-Origin
        corsConfig.setAllowedOrigins(Arrays.asList("*"));
        //允许哪些请求方式的访问
        corsConfig.setAllowedMethods(Arrays.asList("*"));
        //跨域访问时，允许携带的请求头有哪些 (排除cookie的)
        corsConfig.setAllowedHeaders(Arrays.asList("*"));
        //跨域访问时，允许携带的响应头有哪些 (排除cookie的),回去的头
        corsConfig.setExposedHeaders(Arrays.asList("*"));

        //允许携带cookie信息
//        corsConfig.setAllowCredentials();

        //任何资源的访问，都按照我们指定的corsConfig配置来进行跨域限定
        //跨域资源共享(Cross Origin Resource Sharing) CORS
        ubccs.registerCorsConfiguration("/**",corsConfig);
        return ubccs;
    }
}






















